package com.workerhelping.controller;

import com.workerhelping.constant.MQConstant;
import com.workerhelping.dto.RabbitMQDTO;
import com.workerhelping.dto.RecordIdDTO;
import com.workerhelping.dto.WorkerInfoDTO;
import com.workerhelping.dto.WorkerStatusInfoDTO;
import com.workerhelping.elasticsearchEntity.ESRecordVO;
import com.workerhelping.enums.OperationEnum;
import com.workerhelping.enums.RecordStatusEnum;
import com.workerhelping.feignClients.ESFeignClient;
import com.workerhelping.feignClients.MySQLFeignClient;
import com.workerhelping.feignClients.RabbitMQFeignClient;
import com.workerhelping.po.Confirm;
import com.workerhelping.po.Record;
import com.workerhelping.po.StuckReason;
import com.workerhelping.result.Result;
import com.workerhelping.result.ResultCodeEnum;
import com.workerhelping.vo.AdminConfirmVO;
import com.workerhelping.vo.PreviewRecordVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@RestController
@RequestMapping("/adminRecord")
public class AdminRecordController {

    @Autowired
    private ESFeignClient esFeignClient;

    @Autowired
    private RabbitMQFeignClient rabbitMQFeignClient;

    @Autowired
    private MySQLFeignClient mySQLFeignClient;


    @Deprecated
    @GetMapping("/getAllByUnreviewed")
    public Result<Object> getAllByUnreviewed(@RequestParam(value = "pageNo", required = false, defaultValue = "1") Integer pageNo,
                                             @RequestParam(value = "pageSize", required = false, defaultValue = "6") Integer pageSize) {
        Result<Object> findResult = mySQLFeignClient.getAllByUnreviewed(pageNo, pageSize);
        if (!findResult.isOk())
            return Result.fail();
        Object records = findResult.getData();
        if (StringUtils.isEmpty(records))
            return Result.build(null, ResultCodeEnum.DATA_IS_EMPTY);
        return Result.ok(records);
    }

    @Deprecated
    @GetMapping("/getAllByApproved")
    public Result<Object> getAllByApproved(@RequestParam(value = "pageNo", required = false, defaultValue = "1") Integer pageNo,
                                             @RequestParam(value = "pageSize", required = false, defaultValue = "6") Integer pageSize) {
        Result<Object> findResult = mySQLFeignClient.getAllByApproved(pageNo, pageSize);
        if (!findResult.isOk())
            return Result.fail();
        Object records = findResult.getData();
        if (StringUtils.isEmpty(records))
            return Result.build(null, ResultCodeEnum.DATA_IS_EMPTY);
        return Result.ok(records);
    }

    @Deprecated
    @GetMapping("/getAllByRejected")
    public Result<Object> getAllByRejected(@RequestParam(value = "pageNo", required = false, defaultValue = "1") Integer pageNo,
                                             @RequestParam(value = "pageSize", required = false, defaultValue = "6") Integer pageSize) {
        Result<Object> findResult = mySQLFeignClient.getAllByRejected(pageNo, pageSize);
        if (!findResult.isOk())
            return Result.fail();
        Object records = findResult.getData();
        if (StringUtils.isEmpty(records))
            return Result.build(null, ResultCodeEnum.DATA_IS_EMPTY);
        return Result.ok(records);
    }

    @Deprecated
        @GetMapping("/getAllByCancelled")
    public Result<Object> getAllByCancelled(@RequestParam(value = "pageNo", required = false, defaultValue = "1") Integer pageNo,
                                             @RequestParam(value = "pageSize", required = false, defaultValue = "6") Integer pageSize) {
        Result<Object> findResult = mySQLFeignClient.getAllByCancelled(pageNo, pageSize);
        if (!findResult.isOk())
            return Result.fail();
        Object records = findResult.getData();
        if (StringUtils.isEmpty(records))
            return Result.build(null, ResultCodeEnum.DATA_IS_EMPTY);
        return Result.ok(records);
    }


    /**
     * 预览档案
     * 致困原因使用字符串数组展示
     *
     * @param recordIdDTO
     * @return
     */
    @PostMapping("/previewRecord")
    public Result<PreviewRecordVO> previewRecord(@RequestBody RecordIdDTO recordIdDTO) {
        // 查询档案
        Result<Record> recordResult = mySQLFeignClient.getRecordByRecordId(recordIdDTO);
        if (!recordResult.isOk())
            return Result.build(null, ResultCodeEnum.SEARCH_FAIL);
        Record record = recordResult.getData();
        // 查询致困原因
        Result<List<StuckReason>> listResult = mySQLFeignClient.getAllStuckReasonByRecordId(recordIdDTO);
        if (!listResult.isOk())
            return Result.build(null, ResultCodeEnum.SEARCH_FAIL);
        List<StuckReason> stuckReasons = listResult.getData();
        // 构造视图对象
        PreviewRecordVO previewRecordVO = new PreviewRecordVO();
        BeanUtils.copyProperties(record, previewRecordVO);
        ArrayList<String> reasons = new ArrayList<>();
        ArrayList<Integer> reasonsIds = new ArrayList<>();
        for (StuckReason stuckReason : stuckReasons) {
            reasons.add(stuckReason.getReason());
            reasonsIds.add(stuckReason.getId());
        }
        previewRecordVO.setStuckReasonStr(new ArrayList<>(reasons));
        previewRecordVO.setStuckReasonIds(reasonsIds);
        return Result.ok(previewRecordVO);
    }


    /**
     * 批准
     * 需要接收ESRecordVO对象
     *
     * @param esRecordVO
     * @return
     */
    @PostMapping("/agree")
    public Result<String> approve(@RequestBody ESRecordVO esRecordVO) {
        Result<String> result = updateWorkerStatusInfo(esRecordVO, RecordStatusEnum.APPROVED);
        if (!result.isOk())
            return Result.build(null, ResultCodeEnum.APPROVE_FAIL);
        return Result.ok();
    }

    /**
     * 拒绝
     * 需要接收ESRecordVO对象
     *
     * @param esRecordVO
     * @return
     */
    @PostMapping("/reject")
    public Result<String> reject(@RequestBody ESRecordVO esRecordVO) {
        Result<String> result = updateWorkerStatusInfo(esRecordVO, RecordStatusEnum.REJECTED);
        if (!result.isOk())
            return Result.build(null, ResultCodeEnum.REJECT_FAIL);
        return Result.ok();
    }

    /**
     * 注销
     * 需要接收ESRecordVO对象
     *
     * @param esRecordVO
     * @return
     */
    @PostMapping("/cancel")
    public Result<String> cancel(@RequestBody ESRecordVO esRecordVO) {
        Result<String> result = updateWorkerStatusInfo(esRecordVO, RecordStatusEnum.CANCELLED);
        if (!result.isOk())
            return Result.build(null, ResultCodeEnum.CANCEL_FAIL);
        return Result.ok();
    }

    /**
     * 删除
     * 需要接收ESRecordVO对象
     *
     * @param esRecordVO
     * @return
     */
    @PostMapping("/delete")
    public Result<String> delete(@RequestBody ESRecordVO esRecordVO) {
        // 构造WorkerStatusInfoDTO更新mysql
        WorkerInfoDTO workerInfoDTO = new WorkerInfoDTO(
                esRecordVO.getWorkerId(),
                null,
                RecordStatusEnum.UNSUBMITTED.getCode()
        );
        Result<String> updateResult = mySQLFeignClient.updateWorkerInfo(workerInfoDTO);
        if (!updateResult.isOk())
            return Result.fail();
        RecordIdDTO recordIdDTO = new RecordIdDTO(esRecordVO.getId());
        mySQLFeignClient.deleteRecordStuckReasonByRecordId(recordIdDTO);
        Result<String> result = mySQLFeignClient.deleteRecordById(recordIdDTO);
        if (!result.isOk())
            return Result.fail();
        RabbitMQDTO rabbitMQDTO = new RabbitMQDTO(
                MQConstant.EXCHANGE_RECORD,
                MQConstant.ROUTINGKEY_RECORD_DELETE,
                esRecordVO
        );
        boolean isSend = rabbitMQFeignClient.sendMsg(rabbitMQDTO);
        if (updateResult.isOk() && isSend)
            return Result.ok();
        else return Result.fail();
    }


    /**
     * 更新用户档案状态,用于 批准、拒绝、注销
     *
     * @return
     */
    private Result<String> updateWorkerStatusInfo(ESRecordVO esRecordVO, RecordStatusEnum recordStatusEnum) {
        // 构造WorkerStatusInfoDTO更新mysql
        WorkerStatusInfoDTO workerStatusInfoDTO = new WorkerStatusInfoDTO(esRecordVO.getWorkerId(),
                recordStatusEnum.getCode());
        // 构造RabbitMQDTO更新es
        esRecordVO.setStatus(recordStatusEnum.getStatus());
        RabbitMQDTO rabbitMQDTO = new RabbitMQDTO(MQConstant.EXCHANGE_RECORD,
                MQConstant.ROUTINGKEY_RECORD_INSERTORUPDATE,
                esRecordVO);
        Result<String> updateResult = mySQLFeignClient.updateWorkerStatusInfo(workerStatusInfoDTO);
        boolean isSend = rabbitMQFeignClient.sendMsg(rabbitMQDTO);
        if (updateResult.isOk() && isSend)
            return Result.ok();
        else return Result.fail();
    }


    /**
     * 发送审核成功消息
     *
     * @param adminConfirmVO
     * @return
     */
    @PostMapping("/approveConfirm")
    public Result<String> approveConfirm(@RequestBody AdminConfirmVO adminConfirmVO) {
        Result<String> result = commonConfirm(OperationEnum.APPROVE, adminConfirmVO);
        if (!result.isOk())
            return Result.fail();
        return Result.ok();
    }

    /**
     * 发送拒绝消息
     *
     * @param adminConfirmVO
     * @return
     */
    @PostMapping("/rejectConfirm")
    public Result<String> rejectConfirm(@RequestBody AdminConfirmVO adminConfirmVO) {
        Result<String> result = commonConfirm(OperationEnum.REJECTION, adminConfirmVO);
        if (!result.isOk())
            return Result.fail();
        return Result.ok();
    }

    /**
     * 发送注销消息
     *
     * @param adminConfirmVO
     * @return
     */
    @PostMapping("/cancelConfirm")
    public Result<String> cancelConfirm(@RequestBody AdminConfirmVO adminConfirmVO) {
        Result<String> result = commonConfirm(OperationEnum.LOGOUT, adminConfirmVO);
        if (!result.isOk())
            return Result.fail();
        return Result.ok();
    }

    /**
     * 发送删除消息
     *
     * @param adminConfirmVO
     * @return
     */
    @PostMapping("/deleteConfirm")
    public Result<String> deleteConfirm(@RequestBody AdminConfirmVO adminConfirmVO) {
        Result<String> result = commonConfirm(OperationEnum.DELETE, adminConfirmVO);
        if (!result.isOk())
            return Result.fail();
        return Result.ok();
    }


    /**
     * 通用方法：发送档案审核结果
     *
     * @param operationEnum
     * @param confirmVO
     * @return
     */
    private Result<String> commonConfirm(OperationEnum operationEnum, AdminConfirmVO confirmVO) {
        Confirm confirm = new Confirm(
                new Date(),
                operationEnum.getCode(),
                confirmVO.getReason(),
                confirmVO.getWorkerId()
        );
        Result<String> result = mySQLFeignClient.saveConfirm(confirm);
        if (!result.isOk())
            return Result.fail();
        return Result.ok();
    }


    /**
     * 多条件聚合查询
     *
     * @param id                字段查询
     * @param name              模糊查询（三次及以上允许一处容错）
     * @param idNumber          通配符查询
     * @param creditCardNumbers 通配符查询
     * @return
     */
    @GetMapping("/searchByUnreviewed")
    Result<List<ESRecordVO>> findAllByUnreviewed(@RequestParam(value = "sId", required = false) Integer id,
                                                 @RequestParam(value = "sName", required = false) String name,
                                                 @RequestParam(value = "sIdNumber", required = false) String idNumber,
                                                 @RequestParam(value = "sCreditCardNumbers", required = false) String creditCardNumbers) {
        Result<List<ESRecordVO>> recordsResult = esFeignClient.findAllByUnreviewed(id, name, idNumber, creditCardNumbers);
        if (!recordsResult.isOk())
            return Result.fail();
        List<ESRecordVO> records = recordsResult.getData();
        if (records.isEmpty())
            return Result.build(null, ResultCodeEnum.DATA_IS_EMPTY);
        return Result.ok(records);
    }

    @GetMapping("/searchByApproved")
    Result<List<ESRecordVO>> findAllByApproved(@RequestParam(value = "sId", required = false) Integer id,
                                               @RequestParam(value = "sName", required = false) String name,
                                               @RequestParam(value = "sIdNumber", required = false) String idNumber,
                                               @RequestParam(value = "sCreditCardNumbers", required = false) String creditCardNumbers) {
        Result<List<ESRecordVO>> recordsResult = esFeignClient.findAllByApproved(id, name, idNumber, creditCardNumbers);
        if (!recordsResult.isOk())
            return Result.fail();
        List<ESRecordVO> records = recordsResult.getData();
        if (records.isEmpty())
            return Result.build(null, ResultCodeEnum.DATA_IS_EMPTY);
        return Result.ok(records);
    }

    @GetMapping("/searchByRejected")
    Result<List<ESRecordVO>> findAllByRejected(@RequestParam(value = "sId", required = false) Integer id,
                                               @RequestParam(value = "sName", required = false) String name,
                                               @RequestParam(value = "sIdNumber", required = false) String idNumber,
                                               @RequestParam(value = "sCreditCardNumbers", required = false) String creditCardNumbers) {
        Result<List<ESRecordVO>> recordsResult = esFeignClient.findAllByRejected(id, name, idNumber, creditCardNumbers);
        if (!recordsResult.isOk())
            return Result.fail();
        List<ESRecordVO> records = recordsResult.getData();
        if (records.isEmpty())
            return Result.build(null, ResultCodeEnum.DATA_IS_EMPTY);
        return Result.ok(records);
    }

    @GetMapping("/searchByCancelled")
    Result<List<ESRecordVO>> findAllByCancelled(@RequestParam(value = "sId", required = false) Integer id,
                                                @RequestParam(value = "sName", required = false) String name,
                                                @RequestParam(value = "sIdNumber", required = false) String idNumber,
                                                @RequestParam(value = "sCreditCardNumbers", required = false) String creditCardNumbers) {
        Result<List<ESRecordVO>> recordsResult = esFeignClient.findAllByCancelled(id, name, idNumber, creditCardNumbers);
        if (!recordsResult.isOk())
            return Result.fail();
        List<ESRecordVO> records = recordsResult.getData();
        if (records.isEmpty())
            return Result.build(null, ResultCodeEnum.DATA_IS_EMPTY);
        return Result.ok(records);
    }


}
